﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Downplay.Alchemy.Dynamic;

namespace Downplay.Alchemy.Tests.Dynamics {
    [TestFixture]
    public class PropertyTests {

        [Test]
        public void CanSetAndGetStringProperty() {
            dynamic stuff = new Stuff();
            stuff.Foo = "Bar";
            Assert.That((string)stuff.Foo, Is.EqualTo("Bar"));
        }

        [Test]
        public void CanSetAndGetIntProperty() {
            dynamic stuff = new Stuff();
            int number = 42;
            stuff.Foo = number;
            Assert.That((int)stuff.Foo, Is.EqualTo(42));
        }
        [Test]
        public void CanSetAndGetBooleanProperty() {
            dynamic stuff = new Stuff();
            stuff.Foo = true;
            Assert.That((bool)stuff.Foo, Is.EqualTo(true));
            Assert.That((bool)stuff.Foo, Is.Not.EqualTo(false));
        }

        [Test]
        public void NestedPropertiesAreDynamicallyCreated() {
            dynamic stuff = new Stuff();
            stuff.Bar.Car = "zar";
            Assert.That(stuff.Bar, Is.InstanceOf<Stuff>());
            Assert.That((string)stuff.Bar.Car,Is.EqualTo("zar"));
        }

        [Test]
        public void CanSetObjectThenAddNewProperties() {
            // This tests a few behaviours.
            // 1. Setting an object is actually the same as melding
            // 2. The object can then be dynamically extended with new properties
            // 3. We can even set properties that were not originally settable
            // 4. Extracting an interface then presents the overridden values
            dynamic stuff = new Stuff();
            stuff.Foo = new Downplay.Alchemy.Tests.Dynamics.MeldTests.AZoo();
            stuff.Foo.New = "Ooo";
            stuff.Foo.Zoo = "Who";
            Downplay.Alchemy.Tests.Dynamics.MeldTests.IZoo foo = stuff.Foo;
            Assert.That(foo.Goo, Is.EqualTo("Eww")); 
            Assert.That(foo.Zoo, Is.EqualTo("Who"));
            Assert.That((string)stuff.Foo.New, Is.EqualTo("Ooo"));
        }

        [Test]
        public void CapitalizationImpliesDifferentProperties() {

            dynamic stuff = new Stuff();
            stuff.foo = "Zoo";
            stuff.Foo = "Bar";

            Assert.That((string)stuff.foo, Is.EqualTo("Zoo"));
            Assert.That((string)stuff.Foo, Is.EqualTo("Bar"));

        }



        /*
            dynamic stuff = new Stuff();
            stuff.Foo = "bar";
            stuff.Bar.Car = "zar";
            stuff.Hats.Add("Wide", "Tall");
            stuff.Rar.Meld(new {
                Hello = "Goodbye"
            });
            stuff.Far = new {
                And = "Another thing"
            };
            return Content((string)stuff.Json());
        }

        public void MoreTests() {

            // TODO: Move these into a test suite

            dynamic stuff = new Stuff();

            string test = stuff.Hatter.Mad; // Null or error
            stuff.Hatter.Mad = true;
            bool test1 = stuff.Hatter.Mad; // true
            stuff.Hatter.Mad.As = "Foo";
            bool test2 = stuff.Hatter.Mad; // true
            IMad mad = stuff.Hatter.Mad; // mad.As == "Foo"
            stuff.Hatter.Hats.Add("Tall", "Wide", "Bowler");
            IHatter hatter = stuff.Hatter;
            foreach (var hat in hatter.Hats) { } // "Tall", "Wide", "Bowler"
            hatter.Hats.Add("Felt"); // ??
            hatter.Mad = "Most Certainly"; // ??


        }
        public interface IMad {
            string As { get; }
        }
        public interface IHatter {
            string Mad { get; set; }
            IList<String> Hats { get; }
        }
        */
    }
}
